package ualrcdg.shared.dto;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

/**
 * Simple implementation of the "game" object. See CDG XML Specifications: Game Descriptor Files.
 */
public class Game
{
	private final String name;
	private final String description;
	private final String rootTaskId;
		
	private final Character character;
	
	private final HashMap< String, Task > tasks;
	private final HashMap< String, TaskFSM > taskFSMs;
	private final HashMap< String, Rule > rules;
	private final HashMap< String, RuleSet > ruleSets;
	private final HashMap< String, PropertyUpdate > updates;
	private final HashMap< String, PropertyUpdateSet > updateSets;
	private final HashMap< String, Page > pages;
	private final HashMap< String, MediaScript > mediaScripts;
	private final HashMap< String, FileMedia > fileMedia;
	private final ArrayList< String > fileMediaList;
	private final HashMap< String, ChunkMedia > chunkMedia;
	
	/**
	 * Primary constructor
	 *
	 * @param name the name of the Game object to be created
	 * @param description the description of the Game object to be created
	 * @param rootTaskId the rootTaskId of the Game object to be created
	 * @param character the character of the Game object to be created
	 * @param tasks the tasks of the Game object to be created
	 * @param taskFSMs the taskFSMs of the Game object to be created
	 * @param rules the rules of the Game object to be created
	 * @param ruleSets the ruleSets of the Game object to be created
	 * @param updates the updates of the Game object to be created
	 * @param updateSets the updateSets of the Game object to be created
	 * @param pages the pages of the Game object to be created
	 * @param mediaScripts the mediaScripts of the Game object to be created
	 * @param fileMedia the fileMedia of the Game object to be created
	 * @param chunkMedia the chunkMedia of the Game object to be created
	 */
	public Game( String name, String description, String rootTaskId, Character character, 
			Task[ ] tasks, TaskFSM[ ] taskFSMs, Rule[ ] rules, RuleSet[ ] ruleSets, 
			PropertyUpdate[ ] updates, PropertyUpdateSet[ ] updateSets, Page[ ] pages, MediaScript[ ] mediaScripts, 
			FileMedia[] fileMedia, ChunkMedia[] chunkMedia )
	{
		this.name = name;
		this.description = description;
		this.rootTaskId = rootTaskId;
		
		this.character = character;
		
		this.tasks = new HashMap< String, Task >( );
		for( Task t : tasks )
		{
			this.tasks.put( t.getId( ), t );
		}
		this.taskFSMs = new HashMap< String, TaskFSM >( );
		for( TaskFSM tfsm : taskFSMs )
		{
			this.taskFSMs.put( tfsm.getId( ), tfsm );
		}
		
		this.rules = new HashMap< String, Rule >( );
		for( Rule r : rules )
		{
			this.rules.put( r.getId( ), r );
		}
		this.ruleSets = new HashMap< String, RuleSet >( );
		for( RuleSet rs : ruleSets )
		{
			this.ruleSets.put( rs.getId( ), rs );
		}
		
		this.updates = new HashMap< String, PropertyUpdate >( );
		for( PropertyUpdate u : updates )
		{
			this.updates.put( u.getId( ), u );
		}
		this.updateSets = new HashMap< String, PropertyUpdateSet >( );
		for( PropertyUpdateSet us : updateSets )
		{
			this.updateSets.put( us.getId( ), us );
		}
		
		this.pages = new HashMap< String, Page >( );
		for( Page p : pages )
		{
			this.pages.put( p.getId( ), p );
		}
		this.mediaScripts = new HashMap< String, MediaScript >( );
		for( MediaScript ms : mediaScripts )
		{
			this.mediaScripts.put( ms.getId( ), ms );
		}
		
		this.fileMedia = new HashMap< String, FileMedia >( );
		this.fileMediaList = new ArrayList< String >( );
		for( FileMedia fm : fileMedia )
		{
			this.fileMedia.put( fm.getId( ), fm );
			this.fileMediaList.add( fm.getFileName( ) );
		}
		this.chunkMedia = new HashMap< String, ChunkMedia >( );
		for( ChunkMedia cm : chunkMedia )
		{
			this.chunkMedia.put( cm.getId( ), cm );
		}
		
		System.out.println( "Parsed: " + this.toString( ) );
	}

	/*
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString( )
	{
		return "Game [name=" + name + ", description=" + description + ", rootTaskId=" + rootTaskId + ", character=" + character + 
				", tasks=" + tasks + ", taskFSMs=" + taskFSMs + ", rules=" + rules + ", ruleSets=" + ruleSets + 
				", pages=" + pages + ", mediaScripts=" + mediaScripts + ", fileMedia=" + fileMedia + ", chunkMedia=" + chunkMedia + "]";
	}

	/**
	 * @return the name of this Game instance
	 */
	public String getName( )
	{
		return name;
	}

	/**
	 * @return the description of this Game instance
	 */
	public String getDescription( )
	{
		return description;
	}

	/**
	 * @return the rootTask of this Game instance
	 */
	public String getRootTaskId( )
	{
		return rootTaskId;
	}

	/**
	 * @return the character of this Game instance
	 */
	public Character getCharacter( )
	{
		return character;
	}

	/**
	 * @param id the id of the Task to be retrieved
	 * @return the desired Task of this Game instance
	 */
	public Task getTask( String id )
	{
		return tasks.get(id);
	}

	/**
	 * @param id the id of the TaskFSM to be retrieved
	 * @return the desired TaskFSM of this Game instance
	 */
	public TaskFSM getTaskFSM( String id )
	{
		return taskFSMs.get(id);
	}

	/**
	 * @param id the id of the Rule to be retrieved
	 * @return the desired Rule of this Game instance
	 */
	public Rule getRule( String id )
	{
		return rules.get(id);
	}

	/**
	 * @param id the id of the RuleSet to be retrieved
	 * @return the desired RuleSet of this Game instance
	 */
	public RuleSet getRuleSet( String id )
	{
		return ruleSets.get(id);
	}

	/**
	 * @param id the id of the Page to be retrieved
	 * @return the desired Page of this Game instance
	 */
	public Page getPage( String id )
	{
		return pages.get(id);
	}

	/**
	 * @param id the id of the MediaScript to be retrieved
	 * @return the desired MediaScript of this Game instance
	 */
	public MediaScript getMediaScript( String id )
	{
		return mediaScripts.get(id);
	}

	/**
	 * @param id the id of the FileMedia to be retrieved
	 * @return the desired FileMedia of this Game instance
	 */
	public Media getFileMedia( String id )
	{
		return fileMedia.get( id );
	}

	/**
	 * @param id the id of the ChunkMedia to be retrieved
	 * @return the desired ChunkMedia of this Game instance
	 */
	public Media getChunkMedia( String id )
	{
		return chunkMedia.get( id );
	}

	/**
	 * @return the list of all media file names associated with this Game instances
	 */
	public List< String > getFileMediaList( )
	{
		return Collections.unmodifiableList( this.fileMediaList );
	}
}
